import com.google.common.util.concurrent.RateLimiter;
import lombok.extern.slf4j.Slf4j;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@Slf4j
public class RateLimiterDemo1 {

    private static ExecutorService threadPool = Executors.newCachedThreadPool();

    public static void main(String[] args) {
        acqtest();          //阻塞测试
        tryAcqtest();       //非阻塞
        tryAcqtestTimeOut();    //非阻塞超时测试

        threadPool.shutdown();
    }

    private static void acqtest() {
        //代表一秒最多多少个
        RateLimiter rateLimiter = RateLimiter.create(2);
        List<Runnable> tasks = new ArrayList<Runnable>();
        for (int i = 0; i < 10; i++) {
            tasks.add(new UserRequest(i));
        }

        for (Runnable runnable : tasks) {
            rateLimiter.acquire();
//            log.info("等待时间：" + rateLimiter.acquire());//阻塞式
            threadPool.execute(runnable);
        }
    }

    private static void tryAcqtest() {
        RateLimiter rateLimiter = RateLimiter.create(1.1);
        List<Runnable> tasks = new ArrayList<Runnable>();
        for (int i = 0; i < 10; i++) {
            tasks.add(new UserRequest(i));
        }
        for (Runnable runnable : tasks) {
            log.info("非阻塞式 我开始请求了：" + rateLimiter.tryAcquire());//非阻塞式
            if (rateLimiter.tryAcquire()) {
                threadPool.execute(runnable);
            }
        }
    }

    private static void tryAcqtestTimeOut() {
        //代表一秒最多1个请求
        RateLimiter rateLimiter = RateLimiter.create(5);
        List<Runnable> tasks = new ArrayList<Runnable>();
        for (int i = 0; i < 20; i++) {
            tasks.add(new UserRequest(i));
        }
        for (Runnable runnable : tasks) {
            int id = runnable.hashCode();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
            //判断能否在3秒内得到令牌，如果不能则立即返回false，不会阻塞程序
            log.info("+ 我开始请求了：" + id);//非阻塞式
            if (rateLimiter.tryAcquire(1000, TimeUnit.MILLISECONDS)) {
                log.info("* 我拿到令牌了：" + id);//非阻塞式
                threadPool.execute(runnable);
            } else {
                log.info("- 我没拿到令牌：" + id);//非阻塞式
            }
        }
    }

    /**
     * 模仿用户请求的线程
     *
     * @Package :com.test.rateLimiterTest
     * @ClassName:UserRequest
     * @Author :Administrator
     * @Date:2018年9月12日 下午4:00:52
     * @Desc:
     */
    private static class UserRequest implements Runnable {
        private int id;

        public UserRequest(int id) {
            this.id = id;
        }

        public void run() {
            log.info("我是用户请求开始执行：" + id);
        }
    }

}